/*
 *  Copyright 2011 yura.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.vcforms.bean.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.MutableComboBoxModel;

/**
 *  
 * @author yura
 */
public class ComboBoxModel<E extends Object> extends AbstractListModel
        implements MutableComboBoxModel {

    protected List<E> data;
    protected E selected;

    public ComboBoxModel(List<E> data) {
        if (data == null){
            data = new ArrayList<E>();
        }
        this.data = data;
        if (! data.isEmpty()){
            selected = data.get(0);
        }
    }

    public ComboBoxModel() {
        this(null);
    }

    public E get(int index) {
        return data.get(index);
    }

    @Override
    public int getSize() {
        return data.size();
    }

    @Override
    public E getElementAt(int index) {
        return get(index);
    }

    @Override
    @SuppressWarnings("unchecked")
    public void addElement(Object obj) {
        data.add((E) obj);
        fireIntervalAdded(this, data.size() - 1, data.size() - 1);
        if (getSelectedItem() == null){
            setSelectedItem(obj);
        }
    }

    public void addAllElements(Collection<E> newData){
        int size = getSize();
        if (! newData.isEmpty()) {
            data.addAll(newData);
            fireIntervalAdded(this, size, data.size() - 1);
            if (getSelectedItem() == null) {
                setSelectedItem(data.get(data.size() - 1));
            }
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void removeElement(Object obj) {
        int indexOf = data.indexOf((E) obj);
        if (indexOf != -1){
            removeElementAt(indexOf);
        }
    }


    @Override
    @SuppressWarnings("unchecked")
    public void insertElementAt(Object obj, int index) {
        data.add(index, (E) obj);
        fireIntervalAdded(this, index, index);
    }

    @Override
    public void removeElementAt(int index) {
        E obj = data.get(index);
        data.remove(index);
        if (selected == obj || selected != null && selected.equals(obj)) {
            if (index == 0 && getSize() > 0) {
                 setSelectedItem(getElementAt(0));
             } else if (index > 0) {
                 setSelectedItem(getElementAt(index - 1));
             } else {
                 setSelectedItem(null);
             }
        }
    }

    public void removeAllElements(){
        clear();
    }

    public void clear(){
        int size = getSize();
        if (size > 0) {
            data.clear();
            fireIntervalRemoved(this, 0, size - 1);
        }
        setSelectedItem(null);
    }

    public void reset(Collection<E> newData){
        clear();
        addAllElements(newData);
    }

    public void reset(ComboBoxModel newData){
        clear();
        addAllElements(newData.data);
    }

    @Override
    @SuppressWarnings("unchecked")
    public void setSelectedItem(Object anItem) {        
        if (anItem != null && !anItem.equals(selected)
                || anItem == null && selected != null) {
            selected = (E) anItem;
            fireContentsChanged(this, -1, -1);
        }
    }

    @Override
    public E getSelectedItem() {
        return selected;
    }

    public boolean isEmpty() {
        return data.isEmpty();
    }

    public List<E> list(){
        return data;
    }

    @Override
    public String toString() {
        return data!= null? data.toString(): "[nullable]";
    }

}
